﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace Turret
{
    public class TurretRotativeBehaviour : Turret
    {
        //Rotative turret specific stats. See statManager for general turret stats
        [SerializeField]
        private float maxSpeed;
        public float MaxSpeed
        {
            get { return maxSpeed; }
            set { maxSpeed = value; }
        }
        [SerializeField]
        private float minSpeed;
        public float MinSpeed
        {
            get { return minSpeed; }
            set { minSpeed = value; }
        }

        [SerializeField]
        private float acceleration;
        public float Acceleration
        {
            get { return acceleration; }
            set { acceleration = value; }
        }

        [SerializeField]
        private float deceleration;
        public float Deceleration
        {
            get { return deceleration; }
            set { deceleration = value; }
        }


        [SerializeField]
        private float translationSpeed;
        public float TranslationSpeed
        {
            get { return translationSpeed; }
            set { translationSpeed = value; }
        }

        private Vector2 minMaxRange;
        public Transform ball;

        private Transform[] contactBalls;
        private List<GameObject> taggedCloseGameObjects;

        private bool readyToAttack = false;

        protected override void Awake()
        {
            base.Awake();
        }

        // Use this for initialization
		protected override void Start()
        {
            base.Start();

            minMaxRange = new Vector2(5, projectileRange);

            //Tags our turret will focus
            targetableTag[0] = "Ennemy_ground";
            //Create the target list
            taggedCloseGameObjects = new List<GameObject>();
            //Get and keep the contact balls
            contactBalls = new Transform[ball.childCount];
            int index = 0;
            foreach (Transform selectedBall in ball)
            {
                contactBalls[index] = selectedBall;
                index++;
            }
        }

        protected override void getMyStatTemplates()
        {
            statTemplates = statManager.RotativeTurretStat;
        }

        // Update is called once per frame
        protected override void Update()
        {
            base.Update();
            //Animation for not attacking contact balls
            ball.Rotate(Vector3.up * turnSpeed * Time.deltaTime);
            //Remove dead target from the list
            clearTargetList();
            //If we can catch some targets
            if (taggedCloseGameObjects.Count > 0)
            {
                //If all the condition for attacking are set
                if (Time.time > nextFireTime && readyToAttack)
                {
                    fire();
                }
            }
            else
            {
                //If there are no targets around, go back or stay in not attacking mode
                decelerate();
            }
            
        }

        private void clearTargetList()
        {
            for (int i = taggedCloseGameObjects.Count - 1; i >= 0; i--)
            {
                if(null == taggedCloseGameObjects[i])
                {
                    taggedCloseGameObjects.Remove(taggedCloseGameObjects[i]);
                }
            }
        }

        private void decelerate()
        {
            //Reduce the rotation speed of the contact balls base on acceleration & delta time
            turnSpeed -= acceleration * Time.deltaTime;
            //Turret not ready to attack if decelerating
            readyToAttack = false;
            //Keep the speed above minimum
            if (turnSpeed <= MinSpeed)
            {
                turnSpeed = MinSpeed;
            }
            //Get the contact balls closer to the sphere
            if (!(Vector3.Distance(ball.position, contactBalls[0].position) < minMaxRange.x))
            {
                for (int i = 0; i < contactBalls.Length; i++)
                {
                    contactBalls[i].Translate(Vector3.back * translationSpeed * Time.deltaTime);
                }
            }
        }

        private void accelerate()
        {
            //Same as decelerate with acceleration and max speed
            turnSpeed += acceleration * Time.deltaTime;
            if (turnSpeed >= maxSpeed)
            {
                turnSpeed = maxSpeed;
                readyToAttack = true;
            }
            //Same as decelerate used to move contact balls away
            if (!(Vector3.Distance(ball.position, contactBalls[0].position) > minMaxRange.y))
            {
                for (int i = 0; i < contactBalls.Length; i++)
                {
                    contactBalls[i].Translate(Vector3.forward * translationSpeed * Time.deltaTime);
                }
            }
        }

        public override bool canTarget(Collider collider)
        {
            if (ghost)
            {
                return false;
            }
            //Check the tag list for this collider
            for (int index = 0; index < targetableTag.Length; index++)
            {
                if (targetableTag[index] == collider.tag)
                {
                    return true;
                }
            }
            return false;
        }

		protected override void fire()
        {
            //Do AoE damages then update fire timer
            foreach (GameObject obj in taggedCloseGameObjects)
            {
                obj.GetComponent<EnnemyBehaviour>().applyDamages(projectileDamage);
            }

            nextFireTime = Time.time + reloadTime;
        }

        public override void setTarget(GameObject target)
        {
            if (!taggedCloseGameObjects.Contains(target))
            {
                taggedCloseGameObjects.Add(target);
            }
            accelerate();
        }

        public override void targetOutOfRange(GameObject target)
        {
            if (taggedCloseGameObjects.Contains(target))
            {
                taggedCloseGameObjects.Remove(target);
            }
        }

    }
}
